package com.lcredu.annotation;

import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.File;
import java.lang.annotation.Annotation;
import java.net.URL;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author 黎长容
 * @date 2025-07-14 15:04
 * 作用 : 充当容器
 */
public class LcrSpringApplicationContext {
    private Class configClass;
    private final ConcurrentHashMap<String, Object> singletonObjects = new ConcurrentHashMap<>();

    //构造器
    public LcrSpringApplicationContext(Class configClass) {
        this.configClass = configClass;
//        System.out.println("configClass = " + this.configClass);

        //获取要扫描的包
        //1.获取扫描包注解的配置
        ComponentScan componentScan = (ComponentScan) this.configClass.getDeclaredAnnotation(ComponentScan.class);
        //2.获取要扫描的包
        String path = componentScan.value();
        System.out.println("要扫描的包=" + path);


        //获取扫描包下所有的class文件
        //1. 得到一个类的加载器
        ClassLoader classLoader = LcrSpringApplicationContext.class.getClassLoader();

        //2. 通过类的加载器获取到要扫描包的URL
        path = path.replace(".", "/");
        System.out.println("path=" + path);
        URL url = classLoader.getResource(path);
        System.out.println("url=" + url);

        //3.将要加载的资源(.class)进行遍历=>io
        File file = new File(url.getFile());
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            for (File f : files) {
                System.out.println("===================================");
                System.out.println(f.getAbsolutePath());
                String filePath = f.getAbsolutePath();
                if (filePath.endsWith(".class")) {
                    //为了进行反射,需要获取到com.lcredu.component
                    //D:\Code\JavaCode\Spring\spring_quick_start\target\classes\com\lcredu\component\UserService.class
                    int start = filePath.lastIndexOf("\\");
                    System.out.println(start);
                    int end = filePath.lastIndexOf(".");
                    System.out.println(end);
                    String className = filePath.substring(start + 1, end);
                    System.out.println("className=" + className);
                    //获取类的全路径
                    path = path.replace("/", ".");
                    String classFullName = path + "." + className;
                    //进行反射?
                    //进行过滤,判断该类是不是需要注入到容器中
                    try {
                        //对应的是class对象
                        //Class.forName会调用静态方法
                        //classLoader.loadClass不需要
                        //aClass.isAnnotationPresent(Component.class) 判断这个类是否有Component注解
                        Class<?> aClass = classLoader.loadClass(classFullName);
                        if (aClass.isAnnotationPresent(Component.class) || aClass.isAnnotationPresent(Controller.class) || aClass.isAnnotationPresent(Service.class) || aClass.isAnnotationPresent(Repository.class)) {
                            //反射对象,放入容器
                            Object object = Class.forName(classFullName).newInstance();
                            //放入容器
                            singletonObjects.put(StringUtils.uncapitalize(className), object);
                        }
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                }

            }
        }


    }
}
